using GroupSix.Application.Dtos;
using GroupSix.Domain.Repositories;
using GroupSix.Domain.Entity.App;
using GroupSix.Domain.common;
using Microsoft.Extensions.Logging;
using System.Text.Json;

namespace GroupSix.Application.Services;

/// <summary>
/// 操作日志服务
/// </summary>
public class OperationLogService
{
    private readonly IOperationLogRepository _operationLogRepository;
    private readonly ILogger<OperationLogService> _logger;

    public OperationLogService(
        IOperationLogRepository operationLogRepository,
        ILogger<OperationLogService> logger)
    {
        _operationLogRepository = operationLogRepository;
        _logger = logger;
    }

    /// <summary>
    /// 创建操作日志
    /// </summary>
    /// <param name="request">创建请求</param>
    /// <returns>创建结果</returns>
    public async Task<bool> CreateOperationLogAsync(CreateOperationLogRequestDto request)
    {
        try
        {
            var log = new GsOperationLog
            {
                Id = Guid.NewGuid(),
                OperatorId = request.OperatorId,
                OperatorName = request.OperatorName,
                OperationType = request.OperationType,
                Module = request.Module,
                Description = request.Description,
                Details = request.Details,
                Result = request.Result,
                ErrorMessage = request.ErrorMessage,
                IpAddress = request.IpAddress,
                UserAgent = request.UserAgent,
                RequestUrl = request.RequestUrl,
                RequestMethod = request.RequestMethod,
                RequestParams = request.RequestParams,
                ResponseStatusCode = request.ResponseStatusCode,
                ExecutionTime = request.ExecutionTime,
                OperationTime = DateTime.UtcNow,
                CreatedBy = request.OperatorId,
                UpdatedBy = request.OperatorId,
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };

            await _operationLogRepository.CreateAsync(log);

            _logger.LogInformation("操作日志创建成功: {OperatorName} - {OperationType} - {Module}", 
                request.OperatorName, request.OperationType, request.Module);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "创建操作日志失败: {OperatorName} - {OperationType}", 
                request.OperatorName, request.OperationType);
            return false;
        }
    }

    /// <summary>
    /// 获取操作日志列表
    /// </summary>
    /// <param name="query">查询条件</param>
    /// <returns>日志列表</returns>
    public async Task<PageResult<OperationLogDto>> GetOperationLogsAsync(GroupSix.Domain.Repositories.OperationLogQueryDto query)
    {
        try
        {
            var result = await _operationLogRepository.GetLogsByConditionAsync(query);
            
            var dtos = result.Items.Select(MapToDto).ToList();
            
            return new PageResult<OperationLogDto>
            {
                Items = dtos,
                TotalCount = result.TotalCount,
                PageIndex = result.PageIndex,
                PageSize = result.PageSize
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取操作日志列表失败");
            throw;
        }
    }

    /// <summary>
    /// 根据操作人获取日志列表
    /// </summary>
    /// <param name="operatorId">操作人ID</param>
    /// <param name="page">页码</param>
    /// <param name="pageSize">页大小</param>
    /// <returns>日志列表</returns>
    public async Task<PageResult<OperationLogDto>> GetLogsByOperatorAsync(Guid operatorId, int page = 1, int pageSize = 20)
    {
        try
        {
            var result = await _operationLogRepository.GetLogsByOperatorAsync(operatorId, page, pageSize);
            
            var dtos = result.Items.Select(MapToDto).ToList();
            
            return new PageResult<OperationLogDto>
            {
                Items = dtos,
                TotalCount = result.TotalCount,
                PageIndex = result.PageIndex,
                PageSize = result.PageSize
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "根据操作人获取日志列表失败: {OperatorId}", operatorId);
            throw;
        }
    }

    /// <summary>
    /// 根据操作类型获取日志列表
    /// </summary>
    /// <param name="operationType">操作类型</param>
    /// <param name="page">页码</param>
    /// <param name="pageSize">页大小</param>
    /// <returns>日志列表</returns>
    public async Task<PageResult<OperationLogDto>> GetLogsByOperationTypeAsync(string operationType, int page = 1, int pageSize = 20)
    {
        try
        {
            var result = await _operationLogRepository.GetLogsByOperationTypeAsync(operationType, page, pageSize);
            
            var dtos = result.Items.Select(MapToDto).ToList();
            
            return new PageResult<OperationLogDto>
            {
                Items = dtos,
                TotalCount = result.TotalCount,
                PageIndex = result.PageIndex,
                PageSize = result.PageSize
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "根据操作类型获取日志列表失败: {OperationType}", operationType);
            throw;
        }
    }

    /// <summary>
    /// 根据模块获取日志列表
    /// </summary>
    /// <param name="module">模块</param>
    /// <param name="page">页码</param>
    /// <param name="pageSize">页大小</param>
    /// <returns>日志列表</returns>
    public async Task<PageResult<OperationLogDto>> GetLogsByModuleAsync(string module, int page = 1, int pageSize = 20)
    {
        try
        {
            var result = await _operationLogRepository.GetLogsByModuleAsync(module, page, pageSize);
            
            var dtos = result.Items.Select(MapToDto).ToList();
            
            return new PageResult<OperationLogDto>
            {
                Items = dtos,
                TotalCount = result.TotalCount,
                PageIndex = result.PageIndex,
                PageSize = result.PageSize
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "根据模块获取日志列表失败: {Module}", module);
            throw;
        }
    }

    /// <summary>
    /// 根据时间范围获取日志列表
    /// </summary>
    /// <param name="startTime">开始时间</param>
    /// <param name="endTime">结束时间</param>
    /// <param name="page">页码</param>
    /// <param name="pageSize">页大小</param>
    /// <returns>日志列表</returns>
    public async Task<PageResult<OperationLogDto>> GetLogsByTimeRangeAsync(DateTime startTime, DateTime endTime, int page = 1, int pageSize = 20)
    {
        try
        {
            var result = await _operationLogRepository.GetLogsByTimeRangeAsync(startTime, endTime, page, pageSize);
            
            var dtos = result.Items.Select(MapToDto).ToList();
            
            return new PageResult<OperationLogDto>
            {
                Items = dtos,
                TotalCount = result.TotalCount,
                PageIndex = result.PageIndex,
                PageSize = result.PageSize
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "根据时间范围获取日志列表失败: {StartTime} - {EndTime}", startTime, endTime);
            throw;
        }
    }

    /// <summary>
    /// 获取最近的日志列表
    /// </summary>
    /// <param name="page">页码</param>
    /// <param name="pageSize">页大小</param>
    /// <returns>日志列表</returns>
    public async Task<PageResult<OperationLogDto>> GetRecentLogsAsync(int page = 1, int pageSize = 20)
    {
        try
        {
            var result = await _operationLogRepository.GetRecentLogsAsync(page, pageSize);
            
            var dtos = result.Items.Select(MapToDto).ToList();
            
            return new PageResult<OperationLogDto>
            {
                Items = dtos,
                TotalCount = result.TotalCount,
                PageIndex = result.PageIndex,
                PageSize = result.PageSize
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取最近日志列表失败");
            throw;
        }
    }

    /// <summary>
    /// 导出日志
    /// </summary>
    /// <param name="request">导出请求</param>
    /// <returns>导出数据</returns>
    public async Task<List<OperationLogDto>> ExportLogsAsync(ExportLogsRequestDto request)
    {
        try
        {
            var logs = await _operationLogRepository.ExportLogsAsync(request.Query);
            
            var dtos = logs.Select(MapToDto).ToList();
            
            _logger.LogInformation("日志导出成功: {Format} - {Count} 条记录", request.Format, dtos.Count);
            return dtos;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "导出日志失败: {Format}", request.Format);
            throw;
        }
    }

    /// <summary>
    /// 映射到DTO
    /// </summary>
    private OperationLogDto MapToDto(GsOperationLog log)
    {
        return new OperationLogDto
        {
            Id = log.Id,
            OperatorId = log.OperatorId,
            OperatorName = log.OperatorName,
            OperationType = log.OperationType,
            Module = log.Module,
            Description = log.Description,
            Details = log.Details,
            Result = log.Result,
            ErrorMessage = log.ErrorMessage,
            IpAddress = log.IpAddress,
            UserAgent = log.UserAgent,
            RequestUrl = log.RequestUrl,
            RequestMethod = log.RequestMethod,
            RequestParams = log.RequestParams,
            ResponseStatusCode = log.ResponseStatusCode,
            ExecutionTime = log.ExecutionTime,
            OperationTime = log.OperationTime,
            CreatedAt = log.CreatedAt
        };
    }

    /// <summary>
    /// 清理过期日志
    /// </summary>
    /// <param name="beforeDate">清理此日期之前的日志</param>
    /// <returns>清理结果</returns>
    public async Task<bool> CleanupExpiredLogsAsync(DateTime beforeDate)
    {
        try
        {
            var cleanedCount = await _operationLogRepository.CleanupExpiredLogsAsync(beforeDate);
            _logger.LogInformation("清理了 {CleanedCount} 条过期操作日志，日期在 {BeforeDate} 之前。", cleanedCount, beforeDate);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "清理过期操作日志失败");
            return false;
        }
    }

    /// <summary>
    /// 获取清理统计信息
    /// </summary>
    /// <param name="beforeDate">清理日期</param>
    /// <returns>清理统计信息</returns>
    public async Task<CleanupStatisticsDto> GetCleanupStatisticsAsync(DateTime beforeDate)
    {
        try
        {
            // 获取清理前的总日志数
            var totalLogsBefore = await _operationLogRepository.GetTotalLogsCountAsync();
            
            // 获取清理后的总日志数
            var totalLogsAfter = await _operationLogRepository.GetTotalLogsCountAsync();
            
            // 获取清理的日志数量
            var cleanedCount = await _operationLogRepository.GetExpiredLogsCountAsync(beforeDate);
            
            // 估算释放的存储空间（每条日志约500字节）
            var freedSpaceBytes = cleanedCount * 500L;
            
            return new CleanupStatisticsDto
            {
                CleanedCount = cleanedCount,
                CleanupDate = DateTime.UtcNow,
                BeforeDate = beforeDate,
                TotalLogsBefore = totalLogsBefore,
                TotalLogsAfter = totalLogsAfter,
                FreedSpaceBytes = freedSpaceBytes
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取清理统计信息失败");
            throw;
        }
    }

    /// <summary>
    /// 获取日志统计信息
    /// </summary>
    /// <param name="startDate">开始日期</param>
    /// <param name="endDate">结束日期</param>
    /// <returns>统计信息</returns>
    public async Task<object> GetLogStatisticsAsync(DateTime? startDate = null, DateTime? endDate = null)
    {
        try
        {
            var statistics = await _operationLogRepository.GetLogStatisticsAsync(startDate, endDate);
            _logger.LogInformation("获取日志统计信息成功: {StartDate} - {EndDate}", startDate, endDate);
            return statistics;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取日志统计信息失败");
            throw;
        }
    }
} 